-- 此表中存放不同Gtk下均通用的代码
Gtkui = Gtkui or {};

-- 此表中存放不同Gtk特定的代码，通常直接指向Gtk224/Gtk324等
Gtk = Gtk or {};

-- 请求加载相关控件的lua脚本，仅请求
function Gtkui.require_widget_code(class_name)
	-- 判断lua脚本是否存在，存在，加载之
	local curr_path = GtkUtils.get_current_file_path()
	-- 组合出文件名
	local top_name = Gtkui.get_full_function_name(class_name, Gtkui.func_id_enum.generator)
	-- 检查文件是否存在
	if GtkUtils.check_file_exists(curr_path .. top_name .. ".lua") then
		local GenWidget = require(top_name)
		if GenWidget ~= nil then
			return  GenWidget;
		else
			print("[ERROR] require lua code fail! " .. top_name..  ".lua");
		end
	else
		print("[INFO]lua code file not exist: " .. top_name ..  ".lua");
	end
	return nil
end

-- 请求加载相关控件的lua脚本，仅请求
function Gtkui.require_template_code(tmpl_name)
	-- 判断lua脚本是否存在，存在，加载之
	local curr_path = Gtkui.get_template_folder()
	-- 检查文件是否存在
	if GtkUtils.check_file_exists(curr_path .. tmpl_name .. ".tmpl") then
		-- 请求加载模板文件
		local TmplProc = require(tmpl_name)
		if TmplProc ~= nil then
			return  TmplProc;
		else
			print("[ERROR] require lua code fail! " .. tmpl_name..  ".tmpl");
		end
	else
		print("[INFO]lua code file not exist: " .. tmpl_name ..  ".tmpl");
	end
	return nil
end

-- 根据名字获取控件表
function Gtkui.GetGtkFunction(func_name)
	-- 判断相应的函数是否存在，从表Gtk下获取
	return GtkUtils.get_symbol_by_name(func_name, Gtk);
end

-- 请求加载相关控件的lua脚本，并返回一个函数
function Gtkui.require_widget_code_func(class_name, func_id)
	-- 组合出函数名
	local spec_func_name = Gtkui.get_full_function_name(class_name, func_id)
	-- 判断全局符号中，相应的函数是否存在
	local spec_func = Gtkui.GetGtkFunction(spec_func_name);
	-- 如果当前全局符号中不存在此函数，则尝试加载lua脚本
	if spec_func == nil then
		-- 获取控件的lua脚本
		local gen_widget = Gtkui.require_widget_code(class_name)
		if gen_widget == nil then
			return nil;
		end
		-- 再尝试加载一次
		spec_func = Gtkui.GetGtkFunction(spec_func_name);
	end
	-- 有这个函数，调用之
	if spec_func ~= nil then
		if type(spec_func) == "function" then
			return spec_func;
		else
			print("[ERROR] bad function : " .. spec_func_name .. "in Gen" .. class_name .. ".lua");
		end
	else
		print("[INFO] function not exist: " .. spec_func_name .. " in Gen" .. class_name .. ".lua");
	end
	return nil
end

-- 从Widget节点中获取ID、class
function Gtkui.get_gtk_widget_class_and_id(ui_data, widget_node, id_name, class_name)
	-- 至少两个名字
	if (type(id_name) ~= "string" and class_name ~= "string") then
		return nil;
	end
	-- 获取class属性
	local class_node = get_gtk_ui_get_property(ui_data, widget_node, class_name);
	-- class属性必须存在
	if (class_node == nil) then
		print ("[ERROR] BAD Widget miss ".. class_name);
		return nil;
	end
	-- 类名
	local class_name = get_gtk_ui_property_value(ui_data, widget_node, class_node);
	-- 如果有ID属性
	local id_node = get_gtk_ui_get_property(ui_data, widget_node, id_name);
	-- 判断是否为空
	if (id_node ~= nil) then
		local id_value = get_gtk_ui_property_value(ui_data, widget_node, id_node);
		-- 保存ID
		Gtkui.save_widget_id(id_value);
		-- 返回
		return class_name, id_value;
	end
	-- 返回类名，并生成一个ID
	return class_name, Gtkui.request_new_id(class_name);
end

-- 请求加载相关控件的lua脚本，并返回多个函数
function Gtkui.require_widget_code_funcs(class_name, ...)
	-- 获取控件的lua脚本
	local gen_widget = Gtkui.require_widget_code(class_name)
	if gen_widget ~= nil then
		return nil;
	end
	-- 组合出函数名
	local spec_func_names = {}
	for _, func_id in ipairs( ... ) do
		local spec_func_name = Gtkui.get_full_function_name(class_name, func_id)
		-- 判断相应的函数是否存在
		local spec_func = Gtkui.GetGtkFunction(spec_func_name);
		-- 有这个函数，调用之
		if spec_func ~= nil then
			if type(spec_func) == "function" then
				table.insert(spec_func_names, spec_func);
			else
				print("[ERROR] bad function : " .. spec_func_name .. "in " .. top_name .. ".lua");
				return nil;
			end
		else
			print("[INFO] function not exist: " .. spec_func_name .. " in " .. top_name .. ".lua");
			return nil;
		end
	end
	return spec_func_names.unpack();
end

-- 格式化转换内存中的XML数据
function Gtkui.FormatWidgetData(ui_data, widget_node, class_name, id_value)
	print("[DEBUG] Start FormatWidgetData: widget: ".. class_name .. ", id: " .. id_value);
	-- 判断是否有相应的格式化函数
	local fmt_func = Gtkui.require_widget_code_func(class_name, Gtkui.func_id_enum.format);
	-- 如果不为空，则调用之
	if fmt_func ~= nil then
		return fmt_func(ui_data, widget_node, class_name, id_value);
	end
	-- 否则调用通用格式化函数
	return Gtkui.FormatCommonWidget(ui_data, widget_node, class_name, id_value);
end

-- 格式化转换控件的属性字段
local function format_common_widget_attr(ui_data, widget_node, id_value, fmt_func)
	local property = nil;
	-- 遍历所有的属性节点，添加进去
	local attr_node = get_gtk_ui_first_property(ui_data, widget_node);
	-- 循环处理每一个属性
	while attr_node ~= nil do
		local attr_name = get_gtk_ui_property_name(ui_data, widget_node, attr_node);
		local attr_value = get_gtk_ui_property_value(ui_data, widget_node, attr_node);
		-- 获取属性名和属性值
		if attr_name ~= nil and attr_value ~= nil then
			-- 判断属性表是否为空
			if property == nil then
				property = {};
			end
			-- 两个属性，name 和 value
			property[attr_name] = fmt_func(attr_name, attr_value); -- {name = attr_name, value = attr_value};
		else
			print("[ERROR] ".. id_value .. " has bad property name-value pair, name: " .. tostring(attr_name) ..  ", value: " .. tostring(attr_value));
		end

		-- 取得下一属性
		attr_node = get_gtk_ui_next_property(ui_data, widget_node, attr_node);
	end
	return property;
end

-- 格式化返回控件的属性内容，简单返回
function Gtkui.FormatCommonWidgetAttrSimple(ui_data, widget_node, id_value)
	-- 标准格式化控件属性
	return format_common_widget_attr(ui_data, widget_node, id_value, 
							function(attr_name, attr_value)	return attr_value end);
end

-- 格式化转换控件的属性字段
function Gtkui.FormatCommonWidgetAttr(ui_data, widget_node, id_value)
	-- 标准格式化控件属性
	return format_common_widget_attr(ui_data, widget_node, id_value, 
							function(attr_name, attr_value)
								return {name = attr_name, value = attr_value};
							end
	);
end

-- 格式化返回特定XML格式结点的内容，格式特点：父子双层结构，node_formats中指定父结点名与子结点名，子结点的格式类同于property结点
function Gtkui.FormatCommonParentChildsNode(ui_data, widget_node, node_formats, get_key_value)
	-- 格式化返回特定XML格式结点的内容，格式特点：父子双层结构，node_formats中指定父结点名与子结点名，子结点的格式类同于property结点
	local function format_common_parent_childs_node(ui_data, widget_node, node_formats, fmt_func)
		local group_idx = 1;
		local group_nodes = {};
		-- 遍历所有的属性节点，查找到action-widgets结点
		local parent_node = get_gtk_ui_first_child(ui_data, widget_node);
		-- 循环处理每一个属性结点
		while parent_node ~= nil do
			-- 取得结点名
			local parent_name = get_gtk_ui_node_name(ui_data, parent_node);
			-- 比较，是否为父结点名字
			if parent_name == node_formats[1] then
				-- 每个父结点的结果存入一个数组中
				group_nodes[group_idx] = {}
				-- 顺序号
				local node_idx = 1
				-- 循环处理每一个子结点名字
				local child_node = get_gtk_ui_first_child(ui_data, parent_node)
				-- 循环处理每一个属性结点
				while child_node ~= nil do
					-- 取得结点名
					local child_name = get_gtk_ui_node_name(ui_data, child_node);
					-- 比较，是否为action-widgets结点
					if child_name == node_formats[2] then
						local child_data = Gtkui.FormatCommonWidgetAttr(ui_data, child_node, child_name)
						local node2_value = get_gtk_ui_node_value(ui_data, child_node);
						-- 判空
						if node2_value == nil then
							print("[ERROR] missing value in this node.")
						end
						local key = fmt_func(node_idx, node2_value, child_data, "key")
						if group_nodes[group_idx][key] ~= nil then
							print("[ERROR] group nodes has this key value, replace it.")
						end
						-- 根据格式化函数来返回key-value
						group_nodes[group_idx][key] = fmt_func(node_idx, node2_value, child_data, "value")
					end
					-- 取得下一属性
					child_node = get_gtk_ui_next_child(ui_data, parent_node, child_node);
					-- 每次索引往前递增
					node_idx = node_idx + 1;
				end
				-- 继续下一个父结点
				group_idx = group_idx + 1;
			end

			-- 取得下一属性
			parent_node = get_gtk_ui_next_child(ui_data, widget_node, parent_node);
		end
		return group_nodes;
	end

	-- 标准格式化控件属性
	return format_common_parent_childs_node(ui_data, widget_node, node_formats, get_key_value);
end

-- 格式化返回特定XML格式结点的内容，格式特点：父子双层结构，node_formats中指定父结点名与子结点名，子结点的格式类同于property结点
function Gtkui.FormatCommonParentChildsNodeWithIndexValue(ui_data, widget_node, node_formats)
	local fmt_func = function(idx, attr_name, attr_value, type_)
		if type_ == "key" then
			return idx
		else
			return attr_value
		end
	end
	-- 标准格式化控件属性
	return Gtkui.FormatCommonParentChildsNode(ui_data, widget_node, node_formats, fmt_func);
end

-- 格式化返回GtkDialog中扩展的XML格式结点的内容，格式特点：父子双层结构，node_formats中指定父结点名与子结点名，子结点的格式类同于property结点
function Gtkui.FormatCommonParentChildsNodeWithNameValue(ui_data, widget_node, node_formats)
	local fmt_func = function (idx, attr_name, attr_value, type_)
		if type_ == "key" then
			return attr_name
		else
			return attr_value
		end
	end
	-- 标准格式化控件属性
	return Gtkui.FormatCommonParentChildsNode(ui_data, widget_node, node_formats, fmt_func);
end

-- 格式化转换控件的属性结点
function Gtkui.FormatCommonWidgetProperty(ui_data, widget_node, id_value)
	local property = nil;
	-- 遍历所有的属性节点，添加进去
	local child_node = get_gtk_ui_first_child(ui_data, widget_node);
	-- 循环处理每一个属性结点
	while child_node ~= nil do
		-- 取得结点名
		local node_name = get_gtk_ui_node_name(ui_data, child_node);
		-- 比较，是否为property结点
		if node_name == "property" then
			-- 必须有name属性
			local name_attr = get_gtk_ui_get_property(ui_data, child_node, "name");
			-- 有名字的话，就处理之
			if name_attr ~= nil then
				-- 取得属性名
				local name_val = get_gtk_ui_property_value(ui_data, child_node, name_attr);
				-- 取得所有属性名和属性值
				local total_attr = Gtkui.FormatCommonWidgetAttrSimple(ui_data, child_node, id_value);

				-- 至少会有name属性，所以不需要判空了
				-- 如果property结点有value属性，则输出警告信息
				if (total_attr["value"] ~= nil) then
					print("[WARN] ".. id_value .. " property node has value attribute, please check: " .. node_name)
				end

				-- 此结点的值保存在value中
				total_attr["value"] = get_gtk_ui_node_value(ui_data, child_node);

				-- 判空
				if (property == nil) then
					property = {}
				end
				-- 保存到属性表
				property[name_val] = total_attr;
			else
				print("[ERROR] ".. id_value .. " has bad property name-value pair, missing name!");
			end
		end

		-- 取得下一属性
		child_node = get_gtk_ui_next_child(ui_data, widget_node, child_node);
	end
	return property;
end

-- 格式化转换控件的属性结点
function Gtkui.FormatCommonWidgetSignal(ui_data, widget_node, id_value)
	local signal_list = nil;
	-- 遍历并处理信号结点
	local signal_node = get_gtk_ui_first_child(ui_data, widget_node);
	-- 循环处理每一个属性结点
	while signal_node ~= nil do
		-- 取得结点名
		local node_name = get_gtk_ui_node_name(ui_data, signal_node);
		-- 比较，是否为signal结点
		if node_name == "signal" then
			-- 取得信号结点的属性数据
			local signal_data = Gtkui.FormatCommonWidgetAttrSimple(ui_data, signal_node, id_value)
			-- 判空
			if (signal_list == nil) then
				signal_list = {}
			end
			table.insert(signal_list, signal_data);
		end

		-- 取得下一结点
		signal_node = get_gtk_ui_next_child(ui_data, widget_node, signal_node);
	end
	return signal_list;
end

-- 格式化转换控件的属性结点
function Gtkui.FormatCommonWidgetChild(ui_data, widget_node, id_value)
	local child_group = nil;
	local packing_group = nil;
	local attrib_group = nil;
	-- 遍历所有的属性节点，添加进去
	local child_node = get_gtk_ui_first_child(ui_data, widget_node);
	-- 循环处理每一个属性结点
	while child_node ~= nil do
		-- 取得结点名
		local node_name = get_gtk_ui_node_name(ui_data, child_node);
		-- 比较，是否为child结点
		if node_name == "child" then
			-- 必须有object结点
			local object_node = get_gtk_ui_get_child(ui_data, child_node, "object");
			-- 有object结点的话，就处理之
			if object_node ~= nil then
				-- 获取控件ID
				local class_name, id_value = Gtkui.get_gtk_widget_class_and_id(ui_data, object_node, "id", "class");
				-- 递归处理控件
				local object_data = Gtkui.FormatWidgetData(ui_data, object_node, class_name, id_value);
				-- 判空特殊处理
				if child_group == nil then 
					child_group = {}
					-- 此时packing_group也为空
					packing_group = {}
					-- 此时attrib_group也为空
					attrib_group = {}
				end
				-- 正常插入
				table.insert(child_group, object_data)

				-- 判断是否有packing结点
				local packing_node = get_gtk_ui_get_child(ui_data, child_node, "packing");
				-- 有packing结点的话，就处理之
				if packing_node ~= nil then
					-- packing结点仅有属性结点
					local packing_data = Gtkui.FormatCommonWidgetProperty(ui_data, packing_node, id_value);
					-- 如果format_widget_data的接口中，返回了packing结点，则合并之，TODO，待验证
					if object_data.packing ~= nil then
						-- 合并packing节点
						GtkUtils.copy_to_left(packing_data, object_data.packing);
						-- 拷贝走后，移除此对象数据中暂存的packing结点
						object_data.packing = nil;
					end
					table.insert(packing_group, packing_data)
				else -- 没有packing结点
					-- format_widget_data的接口中，如果返回了packing结点，则添加上
					if object_data.packing ~= nil then
						table.insert(packing_group, object_data.packing)
						-- 拷贝走后，移除此对象数据中暂存的packing结点
						object_data.packing = nil;
					else
						table.insert(packing_group, {})
					end
				end

				-- 附加属性结点
				local attr_data = Gtkui.FormatCommonWidgetAttrSimple(ui_data, child_node, id_value);
				-- 有packing结点的话，就处理之
				if attr_data ~= nil then
					table.insert(attrib_group, attr_data)
				else -- 没有attrib结点，则添加一个空结点
					table.insert(attrib_group, {})
				end
			else
				print("[ERROR] ".. id_value .. " has bad property name-value pair, missing name!");
			end
		end

		-- 取得下一属性
		child_node = get_gtk_ui_next_child(ui_data, widget_node, child_node);
	end
	-- 当有子结点，但没有packing结点时，添加一个空结点
	if (child_group ~= nil) and (packing_group == nil) then
		-- 根据子结点数量，添加相应数量的空结点
		packing_group = {}
		for i = 1, GtkUtils.table_length(child_group) do
			table.insert(packing_group, {})
		end
	end
	return child_group, packing_group, attrib_group;
end

-- 寻找父类对象的格式化接口以格式化整个XML数据（
function Gtkui.FormatWidgetDataByParentClass(ui_data, widget_node, class_name, id_value)
	-- 根据类名找到相应Gtk实例
	local curr_class = Gtkui.GetGtkFunction(class_name);
	-- 如果当前全局符号中不存在此函数，则尝试加载lua脚本
	if curr_class == nil then
		-- 获取控件的lua脚本
		local gen_widget = Gtkui.require_widget_code(class_name)
		-- 都找不到，那就调用默认接口，注意，
		-- 这里不能调用Gtkui.format_widget_data，因为可能会发生自递归
		if gen_widget == nil then
			-- 否则调用通用格式化函数
			return Gtkui.FormatCommonWidget(ui_data, widget_node, class_name, id_value);
		end
		-- 再尝试加载一次
		curr_class = Gtkui.GetGtkFunction(class_name);
	end

	-- 取得父类
	if curr_class.parent ~= nil and curr_class.parent.class ~= nil then
		-- 父类不为空，且父类有相应的类名，则将父名作为本身类传递入format_widget_data
		return Gtkui.FormatWidgetData(ui_data, widget_node, curr_class.parent.class, id_value)
	end
	-- 否则调用通用格式化函数
	return Gtkui.FormatCommonWidget(ui_data, widget_node, class_name, id_value);
end

-- 格式化转换内存中的XML数据，待后续转化
function Gtkui.FormatCommonWidget(ui_data, widget_node, class_name, id_value)
	local widget_data = {};

	-- 遍历所有的属性元素，添加进去
	widget_data["property"] = Gtkui.FormatCommonWidgetAttr(ui_data, widget_node, id_value);
	-- 遍历所有的属性结点，添加进去
	local property_list2 = Gtkui.FormatCommonWidgetProperty(ui_data, widget_node, id_value);
	if widget_data["property"] == nil then
		widget_data["property"] = property_list2
	else
		-- 合并属性节点
		GtkUtils.copy_to_left(widget_data["property"], property_list2);
	end

	-- 如果不存在的话，在这里添加ID结点
	if widget_data.property.id == nil then
		widget_data.property.id = {name = "id", value = id_value}
	end

	-- 遍历并处理信号结点
	widget_data["signal"] = Gtkui.FormatCommonWidgetSignal(ui_data, widget_node, id_value);

	-- 递归处理子结点
	local child_widget, packing, attr_data = Gtkui.FormatCommonWidgetChild(ui_data, widget_node, id_value)
	-- 子结点不为空时，添加
	if child_widget ~= nil then
		widget_data["child"] = {}
		widget_data["child"]["widget"] = child_widget
		widget_data["child"]["packing"] = packing
		widget_data["child"]["attribute"] = attr_data
	end

	return widget_data
end

-- 格式化转换内存中的XML数据，待后续转化
function Gtkui.FormatWidgetNode(ui_data, widget_node, class_id_pairs, post_func)
	-- 至少两个名字
	if (type(class_id_pairs) ~= "table") then
		return nil
	end
	if (class_id_pairs[1] == nil or class_id_pairs[2] == nil) then
		return nil
	end
	-- 调用接口格式化转换对象数据
	local widget_data = Gtkui.FormatWidgetData(ui_data, widget_node, class_id_pairs[1], class_id_pairs[2]);
	-- 返回不为空
	if (widget_data ~= nil) then
		-- 调用后处理函数
		if (post_func ~= nil and type(post_func) == "function") then
			post_func(widget_data, class_id_pairs[1], class_id_pairs[2]);
		end
		return widget_data;
	end
	return nil;
end

-- 查找并返回组件列表中，首个自GtkWidget继承下来的组件
function Gtkui.find_first_gtk_widget(widget_list, widget_class_name)
	local function recursion_check_widget_list(widget_class, match_name)
		-- 如果直接就匹配，则返回
		if widget_class.class == match_name then
			return true
		end
		-- 不匹配时，递归检查父控件
		if widget_class.parent ~= nil then
			return recursion_check_widget_list(widget_class.parent, match_name)
		end
		return false
	end
	
	local function CheckWidgetClassList(widget_class_name, match_name)
		-- 如果直接就匹配，则返回
		if widget_class_name == match_name then
			return true
		end
		-- 不匹配时，递归检查父控件 
		local widget_class = Gtkui.GetGtkClass(widget_class_name)
		return recursion_check_widget_list(widget_class, match_name)
	end
	
	for widget_name, widget_info in pairs(widget_list) do
		if CheckWidgetClassList(widget_info.property.class.value, widget_class_name) then
			return widget_name
		end
	end
	return nil;
end

function Gtkui.RenderTmplCode(tmpl_code, env, debug_folder)
	-- 然后应该调用模板解析函数，进行解析并生成代码
	local tmpl = require("template").create_obj()
    -- 如果设置了调试文件夹，则设置调试文件夹
    if debug_folder ~= nil then
        tmpl.set_debug(debug_folder)
    end
	-- 编译模板并执行之
	return tmpl.process_string_to_ret(tmpl_code, env);
end

function Gtkui.RenderTmplFile(tmpl_code, env, debug_folder)
	-- 然后应该调用模板解析函数，进行解析并生成代码
	local tmpl = require("template").create_obj()
    -- 如果设置了调试文件夹，则设置调试文件夹
    if debug_folder ~= nil then
        tmpl.set_debug(debug_folder)
    end
	-- 编译模板并执行之
	return tmpl.process_file_to_ret(tmpl_code, env);
end

-- 补丁代码列表，根据需要添加相应的补丁代码
Gtkui.CodePatchList = {
	-- NOTEBOOK_LABEL_DEFINE
	["NOTEBOOK_LABEL_DEFINE"] = "#define GtkNotebookLabel GtkLabel",
	-- COMBOBOX_CHILD_ENTRY_DEFINE
	["COMBOBOX_CHILD_ENTRY_DEFINE"] = "#define GtkComboBoxChildEntry GtkEntry",
	-- COMBO_CHILD_ENTRY_DEFINE
	["COMBO_CHILD_ENTRY_DEFINE"] = "#define GtkComboChildEntry GtkEntry",
	-- COLOR_SEL_BUTTON_DEFINE
	["COLOR_SEL_BUTTON_DEFINE"] = "#define GtkColorSelDlgButton GtkButton",
	-- FONT_SEL_BUTTON_DEFINE
	["FONT_SEL_BUTTON_DEFINE"] = "#define GtkFontSelDlgButton GtkButton",
	-- DIALOG_CHILD_VBOX_DEFINE
	["DIALOG_CHILD_VBOX_DEFINE"] = "#define GtkDialogChildGtkVBox GtkVBox",
	-- DIALOG_CHILD_BOX_DEFINE
	["DIALOG_CHILD_BOX_DEFINE"] = "#define GtkDialogChildGtkBox GtkBox",
	-- DIALOG_CHILD_HBUTTON_BOX_DEFINE
	["DIALOG_CHILD_HBUTTON_BOX_DEFINE"] = "#define GtkDialogChildGtkHButtonBox GtkHButtonBox",
	-- DIALOG_CHILD_BUTTON_BOX_DEFINE
	["DIALOG_CHILD_BUTTON_BOX_DEFINE"] = "#define GtkDialogChildGtkButtonBox GtkButtonBox",
	-- GTK_UI_MANAGER_CHILD_UI_DEFINE
	["GTK_UI_MANAGER_CHILD_UI_DEFINE"] = "#define GtkUIManagerChildUI const gchar",
	-- GTK_LOAD_GDK_PIX_BUF
	["GTK_LOAD_GDK_PIX_BUF"] = [[class GTK_LOAD_GDK_PIX_BUF
{
    bool init_succ;
    GdkPixbuf* pix_buf;
  public:
	explicit GTK_LOAD_GDK_PIX_BUF(const char* file_name)
	{
		init_succ = false;
		pix_buf = gdk_pixbuf_new_from_file(file_name, nullptr);
		if (pix_buf != nullptr) init_succ = true;
	};
	~GTK_LOAD_GDK_PIX_BUF()
	{
		if (init_succ) g_object_unref(pix_buf);
	};
	GdkPixbuf* get_gdk_pix_buf()
	{
		if (init_succ) return pix_buf;
		return nullptr;
	};
};

#define  GET_GDK_PIX_BUF(file_name) (GTK_LOAD_GDK_PIX_BUF(file_name).get_gdk_pix_buf())]],
	-- GTK_GET_PROPERTY_WIDGET
	["GTK_GET_PROPERTY_WIDGET"] = [[inline GtkWidget* GTK_GET_PROPERTY_WIDGET(GtkWidget* widget, const gchar* property_name)
{
    GtkWidget* result = NULL;
    g_object_get((GObject*)(widget), (const gchar*)(property_name), &result, NULL);
    return result;
}]],
	-- COLOR_SEL_INTER_CHILD_DEFINE
	["COLOR_SEL_INTER_CHILD_DEFINE"] = "#define GtkColorSelectionInterChild GtkColorSelection",
	-- FONT_SEL_INTER_CHILD_DEFINE
	["FONT_SEL_INTER_CHILD_DEFINE"] = "#define GtkFontSelectionInterChild GtkFontSelection",
	-- TOP_WIDGET，与EXT_WIDGET是根据需要来选择的，因此这两个宏定义，实际使用时，只会根据需要选择一个
	["TOP_WIDGET"] = [[#define     TOP_WIDGET(widget)      (GetMainApp()-> widget .get_handle())
#define     EXT_WIDGET(widget)      (__##widget##__inst__.setup_ui()->gtk_handle())]],
	-- EXT_WIDGET，不需要，
	-- TMPL_WIDGET
	["TMPL_WIDGET"] = "#define     TMPL_WIDGET(widget)     (__##widget##__inst__.setup_ui()->gtk_handle())",
	-- GDK_COLOR
	["GDK_COLOR"] = [[inline const GdkColor* GET_GDK_COLOR(const gchar* spec)
{
    static GdkColor color;
    gdk_color_parse(spec, &color);
    return &color;
}]],
	-- GDK_COLOR2
	["GDK_COLOR2"] = [[inline const GdkColor* GET_GDK_COLOR2(const gchar* spec)
{
	if (spec == NULL)
		return NULL;
    static GdkColor color;
    gdk_color_parse(spec, &color);
    return &color;
}]],
	-- GDK_RGBA
	["GDK_RGBA"] = [[inline const GdkRGBA* GET_GDK_RGBA(const gchar* spec)
{
    static GdkRGBA rgba;
    gdk_rgba_parse(&rgba, spec);
    return &rgba;
}]],
	-- GDK_RGBA2
	["GDK_RGBA2"] = [[inline const GdkRGBA* GET_GDK_RGBA2(const gchar* spec)
{
	if (spec == NULL)
		return NULL;
    static GdkRGBA rgba;
    gdk_rgba_parse(&rgba, spec);
    return &rgba;
}]],
	-- ADD_ACCEL_TO_ACTION_GROUP
	["ADD_ACCEL_TO_ACTION_GROUP"] = [[inline void ADD_ACCEL_TO_ACTION_GROUP(GtkActionGroup* group, GtkAction* action, const gchar* key, GdkModifierType modifiers)
{
    gchar *accel_path;
    guint ukey = gdk_keyval_from_name (key);
    accel_path = g_strconcat ("<Actions>/", gtk_action_group_get_name(group), "/", gtk_action_get_name (action), NULL);

    if (gtk_accel_map_lookup_entry (accel_path, NULL))
	    gtk_accel_map_change_entry (accel_path, ukey, modifiers, TRUE);
    else
	    gtk_accel_map_add_entry (accel_path, ukey, modifiers);
    
    /* gtk_action_set_accel_path (action, accel_path); */
    gtk_action_group_add_action_with_accel(group, action, accel_path);

    g_free (accel_path);
}]],
	-- GTK_SIZE_GROUP_LOOKUP
	["GTK_SIZE_GROUP_LOOKUP"] = "#define     GTK_SIZE_GROUP_LOOKUP(top, widget)      (GetMainApp()-> top .get_ui()->lookup_widget_##widget () )",
};

function Gtkui.create_enum_table(tbl, index)
    assert(type(tbl) == "table")
    local enumtbl = {}
    local enumindex = index or 0
    for i, v in ipairs(tbl) do
        enumtbl[v] = enumindex + i
    end
    return enumtbl
end

Gtkui.func_id_enum = Gtkui.create_enum_table({"generator", "gen_widget_data", "format"})

function Gtkui.get_full_function_name(class_name, func_id)
    if func_id == Gtkui.func_id_enum.generator then
        return "Gen" .. class_name
    elseif func_id == Gtkui.func_id_enum.gen_widget_data then
        return "Gen" .. class_name .. "Data"
    elseif func_id == Gtkui.func_id_enum.format then
        return "Format" .. class_name
    end
    return "Format" .. class_name
end

-- 保存控件ID列表
Gtkui.widget_id_list = {}

function Gtkui.request_new_id(class_name)
    local idx = 1
    local prefix = string.lower(string.gsub(class_name, "^Gtk", "")) .. "_"
    -- 死循环
    while true do
        local id_value = prefix .. idx
        -- 如果该ID不存在，则置标志，并返回该ID
        if Gtkui.widget_id_list[id_value] == nil then
            Gtkui.widget_id_list[id_value] = true
            return id_value
        end
        idx = idx + 1
    end
    -- 始终到不了这儿
    return nil
end

function Gtkui.save_widget_id(id_value)
    if Gtkui.widget_id_list[id_value] == nil then
        Gtkui.widget_id_list[id_value] = true
    else
        print("[ERROR] ".. id_value .. " exist same value. !");
    end
end

-- 保存主控件的名称
Gtkui.main_widget_name = "";

-- 返回主控件的名称
function Gtkui.get_main_widget()
    return Gtkui.main_widget_name;
end

-- 设置主控件的名称
function Gtkui.set_main_widget(widget_name)
    Gtkui.main_widget_name = widget_name
end

-- 保存主工程的名称
Gtkui.main_app_name = "GtkMainApp";

-- 返回主工程的名称
function Gtkui.get_main_appname()
    return Gtkui.main_app_name;
end

-- 设置主工程的名称
function Gtkui.set_main_appname(app_name)
    Gtkui.main_app_name = app_name
end

-- 保存模板文件夹
Gtkui.template_folder = "";

-- 返回模板文件夹
function Gtkui.get_template_folder()
    return Gtkui.template_folder;
end

-- 设置模板文件夹
function Gtkui.set_template_folder(folder)
    Gtkui.template_folder = folder
end

-- 保存输出文件夹
Gtkui.output_folder = "./";

-- 返回输出文件夹
function Gtkui.get_output_folder()
    return Gtkui.output_folder;
end

-- 设置输出文件夹
function Gtkui.set_output_folder(folder)
    Gtkui.output_folder = folder
end

Gtkui.base_type_to_gtype_table = {
    ["gboolean"] = "G_TYPE_BOOLEAN",
    ["gchar"] = "G_TYPE_CHAR",
    ["gchararray"] = "G_TYPE_STRING",
    ["gdouble"] = "G_TYPE_DOUBLE",
    ["gfloat"] = "G_TYPE_FLOAT",
    ["gint"] = "G_TYPE_INT",
    ["gint64"] = "G_TYPE_INT64",
    ["glong"] = "G_TYPE_LONG",

    ["guchar"] = "G_TYPE_UCHAR",
    ["guint"] = "G_TYPE_UINT",
    ["guint64"] = "G_TYPE_UINT64",
    ["gulong"] = "G_TYPE_ULONG",
    
    ["GdkPixbuf"] = "GDK_TYPE_PIXBUF",
}

function Gtkui.GlibBaseTypeToGType(type_name)
    if Gtkui.base_type_to_gtype_table[type_name] ~= nil then
        return Gtkui.base_type_to_gtype_table[type_name]
    end
    return "unknown"
end

Gtkui.widget_id_list = {}

-- 返回控件ID
function Gtkui.gen_gtk_widget_id(widget_name)
    local id = Gtkui.widget_id_list[widget_name]
    if (id == nil) then
        id = 0
        Gtkui.widget_id_list[widget_name] = id
    end
    Gtkui.widget_id_list[widget_name] = id + 1
    return id
end

-- 属性排序函数，暂时只按字母顺序排序，后续允许支持类中的属性自定义排序
function Gtkui.pairs(t)
    local a = {}
    for n in pairs(t) do a[#a + 1] = n end
    table.sort(a)
    local i = 0
    return function ()
        i = i + 1
        return a[i], t[a[i]]
    end
end
